package library.image;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.ImageView;

import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import library.logger.Logger;


/**
 * Created by Mr.Fan on 2016/2/18.
 */
public class BitmapThread implements Runnable {

    private static final ExecutorService executor = Executors.newCachedThreadPool();
    private final WeakReference<View> reference;
    private final BitmapOption options;
    private final BitmapCallback callback;
    private final Thread thread = new Thread(this);

    private static final int MSG_CALLBACK = 0x11;
    private static final int MSG_DISPLAY = 0x12;

    public BitmapThread(BitmapOption options) {
        this.options = options;
        this.reference = null;
        this.callback = null;
    }

    public BitmapThread(BitmapOption options, View view) {
        this.reference = new WeakReference<>(view);
        this.options = options;
        this.callback = null;
    }

    public BitmapThread(BitmapOption options, BitmapCallback callback) {
        this.options = options;
        this.callback = callback;
        this.reference = null;
    }

    private Handler mHandler;

    private synchronized Handler getHandler() {
        if (mHandler == null)
            mHandler = new InnerHandler(Looper.getMainLooper());
        return mHandler;
    }

    private static final class InnerHandler extends Handler {
        public InnerHandler() {
        }

        public InnerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            TaskResult result = (TaskResult) msg.obj;
            if (result == null || result.task == null) {
                return;
            }
            switch (msg.what) {
                case MSG_CALLBACK:
                    if (result.task.callback != null)
                        result.task.callback.onBitmapCallback((Bitmap) result.data);
                    break;
                case MSG_DISPLAY:
                    Bitmap bitmap = (Bitmap) result.data;
                    if (result.task.reference != null && bitmap != null) {
                        final View view = result.task.reference.get();
                        if (view != null) {
                            if (view instanceof ImageView) {
                                ImageView iv = ((ImageView) view);
                                if (result.task.options.getScaleType() != null)
                                    iv.setScaleType(result.task.options.getScaleType());
                                iv.setImageBitmap(bitmap);
                                if (result.task.options.getAnimation() != null)
                                    iv.startAnimation(result.task.options.getAnimation());
                            }
//                    else
//                        view.setBackgroundDrawable(new BitmapDrawable(bitmap));
                        }
                    }
                    break;
            }
        }
    }

    private static class TaskResult {
        final BitmapThread task;
        final Object data;

        TaskResult(BitmapThread task, Object data) {
            this.task = task;
            this.data = data;
        }
    }

    @Override
    public void run() {
        try {
            final Bitmap bitmap = doInBackground();
            onPostExecute(bitmap);
        } catch (Exception e) {
            Logger.debug(e);
        }
    }

    protected Bitmap doInBackground() {
        final String key = BitmapCache.key(options);
        Bitmap bitmap = BitmapCache.get(key);
        if (bitmap != null)
            return bitmap;
        if (Thread.interrupted())
            return null;
        final BitmapOption.Source from = options.getFrom();
        if (from !=null && options.getSrc() != null) {
            if (from.equals(BitmapOption.Source.resource)) {
                bitmap = BitmapUtils.getBitmapFromResource(options);
            } else if (from.equals(BitmapOption.Source.assets)) {
                bitmap = BitmapUtils.getBitmapFromAssets(options);
            } else if (from.equals(BitmapOption.Source.file)) {
                bitmap = BitmapUtils.getBitmapFromFile(options);
            } else if (from.equals(BitmapOption.Source.content)) {

            } else if (from.equals(BitmapOption.Source.video)) {
                bitmap = BitmapUtils.getBitmapFromVideoThumbnail(options);
            } else if (from.equals(BitmapOption.Source.url)) {
                bitmap = BitmapUtils.getBitmapFromUrl(options);
            } else if (from.equals(BitmapOption.Source.stream)) {
                bitmap = BitmapUtils.getBitmapFromStream(options);
            }
        } else if (options.getHttpTask() != null) {
            bitmap = BitmapUtils.getBitmapFromUrl(options);
        }
        if (Thread.interrupted())
            return null;
        if (bitmap == null) {
            Logger.debug(new ImageException(from + " ( " + options.getSrc() + " ) "));
            return bitmap;
        }

        if (Thread.interrupted())
            return null;
        if (options.getScaleWidth() != 0 && options.getScaleHeight() != 0) {
            bitmap = BitmapUtils.getScaleBitmap(bitmap, options.getScaleWidth(), options.getScaleHeight());
        }

        if (Thread.interrupted())
            return null;
        if (options.isGrayScale()) {
            bitmap = BitmapUtils.bitmapToGrayScale(bitmap);
        }

        if (Thread.interrupted())
            return null;
        if (options.getCorner() > 0) {
            bitmap = BitmapUtils.bitmapToCorner(bitmap, options.getCorner());
        } else if (options.getCorner() == -1) {
            bitmap = BitmapUtils.bitmapToRound(bitmap, options);
        }

        BitmapCache.add(key, bitmap);
        return BitmapCache.get(key);
    }


    protected void onPostExecute(final Bitmap bitmap) {
        try {
            if (Thread.interrupted()) {
                return;
            }
            Context context = options.getContext();
            if (context == null) {
                return;
            }
            if (callback != null) {
                Message msg = getHandler().obtainMessage();
                msg.what = MSG_CALLBACK;
                msg.obj = new TaskResult(this, bitmap);
                getHandler().sendMessage(msg);
            }
            if (reference != null) {
                Message msg = getHandler().obtainMessage();
                msg.what = MSG_DISPLAY;
                msg.obj = new TaskResult(this, bitmap);
                getHandler().sendMessage(msg);
            }
        } catch (Exception e) {
            Logger.debug(e);
        } finally {
            BitmapTaskHandler.remove(options.getTag(), this);
        }
    }

    public void cancel() {
        thread.interrupt();
    }

    public final void submit() {
        BitmapTaskHandler.addTask(options.getTag(), this);
        synchronized (executor) {
            executor.execute(thread);
        }
//        executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
//        if (BitmapOption.Source.url == options.getFrom() || BitmapOption.Source.video == options.getFrom()) {
//            execute();
//        } else {
//            onPreExecute();
//            onPostExecute(doInBackground());
//        }
    }
}
